package com.xiaoshuidi.cloud.module.report.xxljob;

import com.xiaoshuidi.cloud.framework.tenant.core.aop.TenantIgnore;
import com.xiaoshuidi.cloud.module.report.convert.finance.ReceivableConvert;
import com.xiaoshuidi.cloud.module.report.dal.DO.ContractRentorderDO;
import com.xiaoshuidi.cloud.module.report.dal.DO.report.*;
import com.xiaoshuidi.cloud.module.report.dal.mapper.ContractRentorderMapper;
import com.xiaoshuidi.cloud.module.report.dal.mapper.report.ReportContractDayRentMapper;
import com.xiaoshuidi.cloud.module.report.dal.mapper.report.ReportContractInfoMapper;
import com.xiaoshuidi.cloud.module.report.service.finance.CollectInAdvanceService;
import com.xiaoshuidi.cloud.module.report.service.finance.IncomeDetailReportService;
import com.xiaoshuidi.cloud.module.report.service.finance.ReceivableService;
import com.xiaoshuidi.cloud.module.report.utils.DateUtils;
import com.xxl.job.core.handler.annotation.XxlJob;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.format.DateTimeFormatter;
import java.time.temporal.TemporalAdjusters;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 应收报表job每日5点
 *
 */
@Component
@Slf4j
public class ReportReceivableHandleJob {
    private static final Integer OUTFLOW = 1;
    @Resource
    private ReceivableService receivableService;
    @Resource
    private ReportContractInfoMapper reportContractInfoMapper;
    @Resource
    private ContractRentorderMapper contractRentorderMapper;
    @Resource
    private IncomeDetailReportService incomeDetailReportService;
    @Resource
    private CollectInAdvanceService collectInAdvanceService;
    @Resource
    private ReportContractDayRentMapper reportContractDayRentMapper;

    @XxlJob("reportReceivableHandleJob")
    @TenantIgnore
    public void execute() {
        //获取当月需要统计应收报表的合同
        //根据账单表的此订单支付时间(应收)or此订单实际支付时间（实收）在本月的
        //昨天结束时间
        LocalDate yesterday = LocalDate.now().minusDays(1);
        LocalDateTime end = LocalDateTime.of(yesterday, LocalTime.MAX);
        //本月开始时间
        LocalDateTime start = yesterday.atStartOfDay().with(TemporalAdjusters.firstDayOfMonth());

        List<ContractRentorderDO> rentorderDOList = contractRentorderMapper.selectListByStartAndEnd(start, end);
        List<ReceivableDO> list = new ArrayList<>();
        List<Long> contractIds = rentorderDOList.stream().map(ContractRentorderDO::getBusinessId).collect(Collectors.toList());
        ////获取合同信息
        List<ReportContractInfoDO> contractInfoList = reportContractInfoMapper.selectBatchByContractIds(contractIds);
        String currentMonth = DateUtils.getYesterdayMonth();
        String lastMonth = DateUtils.getLastMonth();
        int monthDays = yesterday.lengthOfMonth();
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
        for (ReportContractInfoDO e : contractInfoList) {
            //期初余额 期末余额 从预收报表获取
            CollectInAdvanceDO advanceDO = collectInAdvanceService.selectRentAdvanceByContractIdAndMonth(e.getContractId());
            if(advanceDO ==null||!advanceDO.getStatisticsMonth().equals(currentMonth)){
                log.error("本月没有预收数据 contractId:{},currentMonth:{}",e.getContractId(),currentMonth);
                continue;
            }
            ReceivableDO receivableDO = ReceivableConvert.INSTANCE.convertAdvance2Receivable(advanceDO);
            receivableDO.setId(null);
            receivableDO.setContractStartDate(e.getStartTime());
            receivableDO.setContractEndDate(e.getEndTime());
            //当月累计权责应收从权责报表获取
            IncomeDetailReportDO incomeDetailDO = incomeDetailReportService.selectDetailsByContractIdInCurrentMonth(e.getContractId(), currentMonth);
            if(incomeDetailDO ==null){
                log.error("本月没有权责数据 contractId:{},currentMonth:{}",e.getContractId(),currentMonth);
                continue;
            }
            receivableDO.setAccPowerIn(incomeDetailDO.getCurOtherReduce().add(incomeDetailDO.getCurRentReduce()));
            //查询账单周期
            ContractRentorderDO contractRentorderDO = contractRentorderMapper.selectRentOrderByContractIdAndDate(e.getContractId(), yesterday);
            if(contractRentorderDO !=null){
                receivableDO.setOrderPeriod(contractRentorderDO.getStartTime().format(formatter)+"~"+contractRentorderDO.getEndTime().format(formatter));
            }
            //查詢月租金
            ReportContractDayRentDO reportContractDayRentDO = reportContractDayRentMapper.selectDayRent(e.getContractId(), monthDays);
            if(reportContractDayRentDO!=null){
                receivableDO.setDayRent(reportContractDayRentDO.getNormalDayRent());
            }

            //本月应收
            BigDecimal receivable = contractRentorderMapper.selectTotalReceivableInCurrentMonth(e.getContractId(),start,end);
            receivableDO.setCurReceivable(receivable==null?BigDecimal.ZERO:receivable);
            //本月已收 账单汇总+iot费用
            BigDecimal received = contractRentorderMapper.selectTotalReceivedInCurrentMonth(e.getContractId(),start,end);
            receivableDO.setCurReceived(received==null?BigDecimal.ZERO:received);
            //本月未收
            BigDecimal notReceived = contractRentorderMapper.selectTotalNotReceivedInCurrentMonth(e.getContractId(),start,end);
            receivableDO.setCurNotReceived(notReceived==null?BigDecimal.ZERO:notReceived);
            //累计应收 累计已收 累计未收
            ReceivableDO lastMonthReceivable = receivableService.selectRentAdvanceByContractIdAndMonth(e.getContractId(), lastMonth);
            if(lastMonthReceivable!=null){
                receivableDO.setAccReceivable(receivableDO.getCurReceivable().add(lastMonthReceivable.getAccReceivable()));
                receivableDO.setAccReceived(receivableDO.getCurReceived().add(lastMonthReceivable.getAccReceived()));
                receivableDO.setAccNotReceived(receivableDO.getCurNotReceived().add(lastMonthReceivable.getAccNotReceived()));
            }else {
                receivableDO.setAccReceivable(receivableDO.getCurReceivable());
                receivableDO.setAccReceived(receivableDO.getCurReceived());
                receivableDO.setAccNotReceived(receivableDO.getCurNotReceived());
            }
            BigDecimal curAdvance = contractRentorderMapper.selectCurAdvance(e.getContractId());
            receivableDO.setCurAdvance(curAdvance==null?BigDecimal.ZERO:curAdvance);
            list.add(receivableDO);
        }
        //查询当月是否已经生成过预收明细收入
        List<Long> ids = list.stream().map(ReceivableDO::getContractId).collect(Collectors.toList());
        List<ReceivableDO> receivableDOS = receivableService.selectReceivableInCurrentMonth(DateUtils.getYesterdayMonth(),ids);
        if (CollectionUtils.isEmpty(receivableDOS)) {
            receivableService.batchInsert(list);
        }else {
            //不为空则修改
            list.forEach(e->{
                receivableDOS.forEach(report->{
                    if(e.getContractId().equals(report.getContractId())){
                        e.setId(report.getId());
                    }
                });
            });
            List<ReceivableDO> updateList = list.stream().filter(e -> e.getId() != null).collect(Collectors.toList());
            List<ReceivableDO> insertList = list.stream().filter(e -> e.getId() == null).collect(Collectors.toList());
            if (org.apache.commons.collections4.CollectionUtils.isNotEmpty(updateList)) {
                receivableService.batchUpdate(updateList);
            }
            if (org.apache.commons.collections4.CollectionUtils.isNotEmpty(insertList)) {
                receivableService.batchInsert(insertList);
            }
        }
    }

}